/* 
 * Autores:
 *      Jonathan Lopez  11106
 *      Jorge Martínez  11237
 * 
 * Archivo: RegPuertos.java
 * Última Revision: $Rev: 64 $
 *      Fecha: $Date: 2011-09-18 02:32:49 +0000 (Sun, 18 Sep 2011) $
 */ 

package Manejo.Transporte.Registros;

import java.util.HashMap;
import java.util.ArrayList;

import Manejo.Transporte.Puerto;
import Archivador.*;

/**
 * Contiene el registro de todos los Puertos a utilizar en el programa.
 * 
 * @author Jonathan López
 * @author Jorge Martinez
 */
public class RegPuertos {
    private HashMap<ID, Puerto> puertos;
    private HashMap<String, ID> nombrePuertos;
    
    private String nombreRegistro = "RegistroPuertos";
    
    /**
     * Construye el registro de Puertos
     */
    public RegPuertos()
    {
        puertos=new HashMap<ID, Puerto>();
        nombrePuertos=new HashMap<String, ID>();
    }
    
    /**
     * Lee las Navieras desde la base de datos
     */
    public void inicializar( Registros registros )
    {
        // Leer los Puertos de la base de datos
        String[] infoPuertos = Archivador.leerRegistro(nombreRegistro);
        if( infoPuertos != null ){
            for( String linea: infoPuertos ){
                if( !linea.equals("") && !leerPuerto( linea, registros ) )
                    System.out.println("*ERROR RegPuertos* - No se pudo leer Puerto");
            }
        }
    }
    
    /**
     * Guarda el registro de Puertos
     */
    public void guardarTodo(){
        // Serializa todos los Puertos
        ArrayList<String> lineaPuertos = new ArrayList<String>();
        
        for( String nombrePuerto: nombrePuertos.keySet() ){
            ID idPuerto = nombrePuertos.get( nombrePuerto );
            
            String srIdentificador = "[" + nombrePuerto + iArchivable.separador +
                    idPuerto.guardar() + "]";
            String srPuerto = puertos.get(idPuerto).guardar();
            
            lineaPuertos.add( srIdentificador + iArchivable.separadorObjetos +
                    srPuerto );
        }
        
        // Guarda el registro
        if( lineaPuertos.isEmpty() )
            lineaPuertos.add("");
        
        Archivador.guardarRegistro(nombreRegistro,
                lineaPuertos.toArray( new String[0] ));
    }
    
    /**
     * Agrega un nuevo Puerto al registro y le asigna un ID, además se puede
     * asociar el puerto con un nombre el cual debe ser único.
     * @param nuevoPuerto Puerto a agregar
     * @param nombre nombre del puerto a agregar
     * @return nuevo ID del Puerto, o idNulo si la operación falla
     */
    public ID agregarPuerto( Puerto nuevoPuerto, String nombre )
    {
        // Verificar que el nombre del puerto sea único
        if( !nombre.equals("") )
            if( nombrePuertos.containsKey(nombre) )
                return ID.idNulo;
        
        ID nuevoID = GeneradorID.nuevoID();
        while( puertos.containsKey( nuevoID ) ){
            // Muy improbable
            // TODO: notificar al log por cada uno de estos casos
            nuevoID = GeneradorID.nuevoID();
        }
        
        puertos.put( nuevoID, nuevoPuerto );
        if( !nombre.equals("") )
            nombrePuertos.put(nombre, nuevoID);
        return nuevoID;
    }
    
    /**
     * Regresa el Puerto asociado con el ID dado
     * @param idPuerto ID del Puerto a buscar
     * @return Puerto asociado al ID o null si no se encuentra
     */
    public Puerto obtenerPuerto( ID idPuerto )
    {
        return puertos.get( idPuerto );
    }
    
    /**
     * Regresa el puerto asociado al nombre dado
     * @param nombre nombre del puerto asociado al registro
     * @return Puerto asociado, o null si no se encuentra
     */
    public Puerto obtenerPuerto( String nombre )
    {
        ID idPuerto = nombrePuertos.get( nombre );
        if( idPuerto != null )
            return obtenerPuerto( idPuerto );
        else
            return null;
    }
    
    /**
     * Regresa un arreglo con todos los Puertos contenidos en el registro
     * @return Puerto[] con todos los Puertos en el registro
     */
    public Puerto[] obtenerTodosPuertos()
    {
        return puertos.values().toArray( new Puerto[0] );
    }
    
    /**
     * Regresa el nombre del Puerto en base a su ID
     * @param idPuerto
     * @return 
     */
    public String obtenerNombre( ID idPuerto )
    {
        if( nombrePuertos.containsValue(idPuerto) ){
            for (String nombreActual : nombrePuertos.keySet()) {
                if( nombrePuertos.get(nombreActual).equals(idPuerto) )
                    return nombreActual;
            }
        }
        
        return "";
    }
    
    /**
     * Regresa un arreglo con todos los nombre de puertos asociados
     * @return String[]
     */
    public String[] obtenerNombresDePuertos()
    {
        return nombrePuertos.keySet().toArray( new String[0] );
    }
    
    /**
     * Regresa el ID de un Puerto
     * @param puertoObjetivo 
     * @return ID del Puerto
     */
    public ID obtenerID( Puerto puertoObjetivo )
    {
        for( ID id: puertos.keySet() ){
            if( puertos.get(id).equals( puertoObjetivo) )
                return id;
        }
        
        return ID.idNulo;
    }
    
    /**
     * Regresa el ID de un Puerto, dado por su nombre.
     * @param nombrePuerto Nombre del Puerto a buscar
     * @return ID del Puerto o idNulo si no existe
     */
    public ID obtenerID( String nombrePuerto ){
        for( String nombre: nombrePuertos.keySet() ){
            if( nombre.endsWith(nombrePuerto) )
                return nombrePuertos.get(nombre);
        }
        return ID.idNulo;
    }
    
    /**
     * Elimina un Puerto del registro según su ID
     * @param idPuerto ID del Puerto a eliminar
     * @return el Puerto asociada al ID dado, o null si no existía
     */
    public Puerto eliminarPuerto( ID idPuerto )
    {
        // Eliminar la referencia de nombre del puerto si es que existe
        if( nombrePuertos.containsValue( idPuerto ) ){
            nombrePuertos.values().remove( idPuerto );
        }
        
        return puertos.remove( idPuerto );
    }
    
    /**
     * Lee un solo Puerto a partir de una línea de registro.
     * @param linea
     * @return 
     */
    private boolean leerPuerto(String linea, Registros registros)
    {
        String[] partes = linea.split( iArchivable.separadorObjetos, 2 );
        if( partes.length != 2 )
            return false;
        
        // Interpreta el ID del Puerto
        String srIdentificador = Util.eliminarExtremos( partes[0] );
        String[] partesIdentificador = srIdentificador.split( iArchivable.separador );
        if( partesIdentificador.length != 2 )
            return false;
        
        String nombre = partesIdentificador[0];
        ID idPuerto = ID.parseID( partesIdentificador[1] );
        if( idPuerto.equals( ID.idNulo ) )
            return false;
        
        // Interpreta el Puerto
        Puerto puertoActual = Puerto.parsePuerto( partes[1], registros );
        if( puertoActual == null )
            return false;
        
        // Agrega el nuevo Puerto
        puertos.put( idPuerto, puertoActual );
        nombrePuertos.put( nombre, idPuerto );
        return true;
    }
}
